package cn.hzc.fortess.system.service;

import cn.hzc.fortess.core.common.annotion.CURDLog;
import cn.hzc.fortess.core.common.annotion.CURDType;
import cn.hzc.fortess.core.common.constant.Const;
import cn.hzc.fortess.core.shiro.ShiroKit;
import cn.hzc.fortess.system.common.AttrDataPriority;
import cn.hzc.fortess.system.common.EnableStatus;
import cn.hzc.fortess.system.dao.MenuDao;
import cn.hzc.fortess.system.dao.RoleDao;
import cn.hzc.fortess.system.entity.Project;
import cn.hzc.fortess.system.entity.Role;
import cn.hzc.fortess.system.page.Pagination;
import cn.hzc.fortess.system.vo.ResourceAttrVO;
import com.google.common.collect.Lists;
import cn.hzc.fortess.system.search.RoleSearch;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl implements RoleService {


    @Autowired
    RoleDao roleDao;
    @Autowired
    private ProjectService projectService;
    @Autowired
    MenuDao menuDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "新增角色")
    public void add(Role entity) {
        entity.setCreateTime(new Date());
        entity.setCreateUser(ShiroKit.getUser().getAccount());
        roleDao.insert(entity);

    }

    @Override
    @CURDLog(value = "更新角色", curdType = CURDType.EDIT)
    public void update(Role entity) {
        entity.setUpdateTime(new Date());
        entity.setUpdateUser(ShiroKit.getUser().getAccount());
        roleDao.update(entity);
    }

    @Override
    @CURDLog(value = "删除角色", curdType = CURDType.DELETE)
    public void delete(Integer id) {
        roleDao.delete(id);
        roleDao.deleteRelationByRole(id);
    }

    @Override
    public Role getById(Integer id) {
        return roleDao.findById(id);
    }

    @Override
    public List<Role> getByUser(Integer userId) {
        List<Role> roles = roleDao.findByUserId(userId);
        if (CollectionUtils.isEmpty(roles)) {
            roles = Lists.newArrayList();
        }
        roles.removeIf(role -> Objects.equals(role.getStatus(), EnableStatus.DISABLE.getStatus()));
        return roles;
    }

    @Override
    public List<Role> getByProjectId(Integer projectId) {
        List<Role> roles = roleDao.findByProjectId(projectId);
        return CollectionUtils.isEmpty(roles) ? Lists.newArrayList() : roles;
    }


    @Override
    public Pagination getPage(RoleSearch search) {
        if (!ShiroKit.getUser().isAdministrator()) {
            search.setProjectIds(projectService.getUserProjectIds());
        }
        Pagination pagination = new Pagination();
        pagination.setCount(roleDao.count(search));
        if (pagination.getCount() > 0) {
            pagination.setData(roleDao.page(search));
        }
        return pagination;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "删除项目所有角色", curdType = CURDType.DELETE)
    public void deleteByProject(Integer projectId) {
        List<Role> roles = getByProjectId(projectId);
        if (!CollectionUtils.isEmpty(roles)) {
            roles.stream().forEach(role -> delete(role.getId()));
        }
    }

    @Override
    @CURDLog(value = "新增角色")
    public void createAdminRole4Project(Project project) {
        //创建项目管理员
        Role role = new Role();
        role.setIsAdmin(1);
        role.setLesseeId(0);
        role.setProjectId(project.getId());
        role.setRoleClz(0);
        role.setRoleName(project.getProjectName() + "项目管理员");
        role.setStatus(EnableStatus.ENABLE.getStatus());
        role.setMemo("项目内置角色");
        role.setCreateTime(new Date());
        role.setCreateUser(ShiroKit.getUser().getAccount());
        roleDao.insert(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "设置角色权限", curdType = CURDType.SETTING)
    public void setAuthority(Integer roleId, String[] menuIds) {
        roleDao.clearRoleResourceAuth(roleId);
        int i = 0;
        for (String resourceId : menuIds) {
            if ("0".equals(resourceId)
                    || resourceId.startsWith("-")
                    || StringUtils.isBlank(resourceId)) {
                continue;
            }
            roleDao.saveRoleResourceAuth(roleId, Integer.parseInt(resourceId));
            i++;
        }
        final Role role = roleDao.findById(roleId);
        role.setResourceCount(i);
        roleDao.update(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "保存角色用户", curdType = CURDType.SETTING)
    public void saveRoleUser(Integer roleId, String[] userIds) {


        roleDao.clearRoleUser0(roleId, ShiroKit.getUser().isAdministrator() ? null : Const.SAM_LESSEE_ID);


        for (String userId : userIds) {
            if ("0".equals(userId)
                    || userId.startsWith("-")
                    || StringUtils.isBlank(userId)) {
                continue;
            }
            roleDao.saveRoleUser(roleId, Integer.parseInt(userId));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog(value = "设置角色数据权限", curdType = CURDType.SETTING)
    public void setDataAuthority(Integer roleId, List<ResourceAttrVO> attrs) {
        roleDao.clearRoleDataResourceAuth(roleId);
        for (ResourceAttrVO attrVO : attrs) {
            roleDao.saveRoleDataResourceAuth(roleId, attrVO.getResourceId(),
                    attrVO.getId(),
                    attrVO.getAttrAuth(),
                    AttrDataPriority.findPriority(attrVO.getAttrAuth()));
        }
    }

    @Override
    public List<String> findMenuPermissionListByRoleIds(List<Integer> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Lists.newArrayList();
        }
        List<String> resourcePermissionList = menuDao.findMenuPermissionListByRoleId(roleIds);
        if (CollectionUtils.isEmpty(resourcePermissionList)) {
            return Lists.newArrayList();
        }
        return resourcePermissionList;
    }

}
